package mutation_selection;

import java.util.Random;

public class MutaSelektionSimple_Projekt {
	private double arrBest[];
	private Random r;
	private int maxRunden;
	
	public MutaSelektionSimple_Projekt (int grad, int maxRunden)
	{
		this.maxRunden = maxRunden;

		r = new Random(); 
		arrBest = new double[grad+1];
		mutation(arrBest); /* Erzeuge einfach mal was */
			
	}
	
	/**
	 * berechnet Abstand zwischen zielWert und wert
	 **/
	public double eval(double a[])
	{
		
		double sin, erg, dif;
		double max = 0;
		double fitness = 0;

		for (double x = 0; x <= Math.PI/2 + 0.1 ; x += 0.1) {
			erg = 0;
			for(int i = 0; i < a.length; i++)
			{
				erg += a[i] * Math.pow(x, i);
			}
            sin = Math.sin(x); 
            dif = sin-erg;
            max = Math.max(max, Math.max(max, Math.abs(dif)));
            fitness += Math.abs(dif);			
        }
		return fitness; /* fitness => von Heinrich; max => von Grams .... die Bewertung der Funktion*/
	}
	
	public void optimieren() {
		
		int aufwand = 0;
		double arrNeu[] = new double[arrBest.length];
		double fitnessBest, fitnessNeu;
		
		fitnessBest = eval(arrBest);
		System.out.println("Fitness alt\t\t\t neu");
		for(int i = 0; i < maxRunden; i++)
		{
			mutation(arrNeu); 
			// Selektion
			fitnessNeu = eval(arrNeu);
			if(fitnessBest > fitnessNeu)	{
				System.out.println(fitnessBest + "\t\t" + fitnessNeu);
				arrBest = arrNeu.clone();
				fitnessBest = fitnessNeu;
			}
			aufwand++;
		}
		System.out.println("*ENDE*");
		System.out.println("Ergebnis: " + wz(arrBest));
		System.out.println("Fitness: " + fitnessBest);
		System.out.println("Aufwand: " + aufwand); //Schleifen Durchlaeufe
	}
	
	public void mutation(double a[])
	{
		for (int i = 0; i < a.length; i++) {
			a[i] = r.nextGaussian() % 1.0;
		}
				
	}
	
	public String wz(double arr[])
	{
		String wzgrapher = "";
		for(int i = 0; i < arr.length; i++){
			 
			wzgrapher += Math2.round(arr[i],4) + "*x^" + i + "+";
		}
		wzgrapher = wzgrapher.substring(0,wzgrapher.length()-1) +";";
		return wzgrapher;
	}
	
	public static void main(String[] args) {
		int grad = 2;
		for(int i = 0; i < 5;i++) {
			MutaSelektionSimple_Projekt m = new MutaSelektionSimple_Projekt(grad, 100000);
			m.optimieren();
		}
	}
}
